package tp.tecnicasdisenio.model.mail;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Properties;

import javax.mail.Flags;
import javax.mail.Folder;
import javax.mail.Header;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.search.FlagTerm;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import tp.tecnicasdisenio.dao.impl.jdbc.MensajeDao;
import tp.tecnicasdisenio.model.entity.Materia;
import tp.tecnicasdisenio.model.entity.MensajeSMTPMIME;

public class MailDownloader {

  private static final String IMAP = "imaps";
  private static final String POP3 = "pop3";

  private static MensajeDao mensajeDao = MensajeDao.getInstance();

  /**
   * Retrieves the messages from the e-mail account.
   * 
   * @param unreadMessagesOnly If <code>true</code> obtains only unread
   *          messages and marks them as read after processing them; otherwise
   *          obtains all messages in the inbox.
   * @param materiaData The subject whose e-mail data will be used to retrieve
   *          all its e-mails.
   */
  public static void getMessages(final boolean unreadMessagesOnly,
      final Materia materiaData) {
    Properties props = System.getProperties();
    String host = materiaData.getHost();
    boolean isPop = StringUtils.containsIgnoreCase(host, "pop");
    props.setProperty("mail.store.protocol", isPop ? POP3 : IMAP);
    Session session = Session.getDefaultInstance(props, null);
    try {
      Store store = session.getStore(isPop ? POP3 : IMAP);
      store.connect(host, materiaData.getEmail(),
          materiaData.getPassword());
      Folder inbox = store.getFolder("Inbox");
      Message messages[];
      if (unreadMessagesOnly) {
        inbox.open(Folder.READ_WRITE);
        FlagTerm searchTerm = new FlagTerm(new Flags(Flags.Flag.SEEN), false);
        messages = inbox.search(searchTerm);
      } else {
        inbox.open(Folder.READ_ONLY);
        messages = inbox.getMessages();
      }
      for (Message message : messages) {
        StringWriter writer = new StringWriter();
        StringBuilder fullHeaders = new StringBuilder();
        @SuppressWarnings("rawtypes")
        Enumeration headers = message.getAllHeaders();
        while (headers.hasMoreElements()) {
          Header header = (Header) headers.nextElement();
          fullHeaders.append(header.getName()).append(": ")
              .append(header.getValue()).append("\n");
        }
        fullHeaders.append("\n");
        writer.append(fullHeaders.toString());

        InputStream inputStream = message.getInputStream();
        IOUtils.copy(inputStream, writer, "UTF-8");
        String mimeString = writer.toString();

        // Se necesita para "marcar como leído".
        @SuppressWarnings("unused")
        Object content = message.getContent();

        MensajeSMTPMIME mime = new MensajeSMTPMIME();
        mime.setMime(mimeString);
        mime.setProcesado(false);
        mime.setAplicoARegla(false);
        mensajeDao.insertar(mime);
        System.out.println("Nuevo MIME ID: " + mime.getId());
      }
      inbox.close(false);
      store.close();
    } catch(NoSuchProviderException e) {
      e.printStackTrace();
    } catch(MessagingException e) {
      e.printStackTrace();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }

}
